(function($) {
	var defaults = {
		'type': 'html',	//'pdf'
		'target': '_blank', //_self	override a target de link
		'url': '', //x defecto href
		'data': '',	//datos adicionales x defecto     param1=valor1&param3=valor2   o   {param1:valor1,param2:valor2}
		'title': 'ERP ADCSoft', //x defecto title de link
		'form': [], //conpuesto x varios params	o por texto del tipo 'campo_numero1'
		'callback': '', //funcion a realizar despues de enviar el reporte
		'on_show':'', //funcion callback a ejecutar después de haberse mostrado el formulario: pasa como paramestros el, $(dialogo)
		'description':'', //descripcion de lo que debe hacer el usuario
		'data_send_type':'get', //'post' 'method'   metodo de envio de datos al reporte
                'enctype':'',
		//MODAL WINDOW
		'modal':false,
		'position':'center',
		'zIndex':1000,
		//EVENTOS
		'close_on_submit':true	//cerrar la ventana modal automáticamente al enviar los datos
		},
		params_tmpl={
			'div':false,
			'id':'',		//id y name de campo
			'name':'',		//id y name de campo
			'label': '',	//label de campo si no existe, se utiliza el id en camelcase
			'type': 'text',	//checkbox select textarea hidden date
			'date_format': 'dd/mm/yy', //formato por defecto del campo date ver http://docs.jquery.com/UI/Datepicker/formatDate para detalles
			'options': [],	//compuesto por varias opciones
			'value': '',	//value del input
			'html_attribs': [],	//atributos adicionales html 
			'not_required': false, //por defecto todos los campos son requeridos, para obiar esta regla sobre este campo debe ser TRUE
			'mask':'' //mascara de entrada para campos de texto. ver http://www.meiocodigo.com/projects/meiomask/ para mayor detalle
		},
		options_tmpl={
			'text':'',
			'value':''
		},
		attribs_tmpl={
			'attrib':'',
			'value':''
		};
	
	$.fn.adcReport = function(action, options){
		function unbind_el(el){
			el.removeData('adc_report:options').unbind('click').unbind('adcReport');
			debug('unbind_el', el.data());
		}
		
		function setOptions(el){
			//obteniendo parametros del enlace
			lnk_params = {};
			if (el.attr('target')){lnk_params.target = el.attr('target');}
			if (el.attr('href')){lnk_params.url = el.attr('href');}
			if (el.attr('title')){lnk_params.title = el.attr('title');}
			
			opts = $.extend({}, defaults, el.data('adc_report:options'), lnk_params, options);
			if(typeof opts.data=='object'){
				opts.data = $.param(opts.data);
			}
			
			//validando campos para el formulario de envio
			for(i=0, j=opts.form.length; i<j; i++){
				
				//si el campo de formulario es texto y no un objeto, la etiqueta y el id del campo serán el mismo
				if(typeof opts.form[i] == 'string'){
					opts.form[i] = $.extend({},params_tmpl,{'label':opts.form[i].toCamel(), 'id':opts.form[i]});
				}
				
				//estandarizando valores del formulario
				opts.form[i] = $.extend({}, params_tmpl, opts.form[i]);
				if(!opts.form[i].label){
					opts.form[i].label = opts.form[i].id.toCamel();
				}
				
				//estandarizando opciones
				for(m=0, n=opts.form[i].options.length; m<n; m++){
					opts.form[i].options[m] = $.extend({}, options_tmpl, opts.form[i].options[m]);
				}
				
				class_found = '';
				//estandarizando atributos
				if(!opts.form[i].html_attribs.length){
					opts.form[i].html_attribs = [];
				}
				for(m=0, n=opts.form[i].html_attribs.length; m<n; m++){
					opts.form[i].html_attribs[m] = $.extend({}, attribs_tmpl, opts.form[i].html_attribs[m]);
					if(opts.form[i].html_attribs[m].attrib == 'class'){
						class_found = m;
					}
				}
				
				if (opts.form[i].not_required === false){
					if(class_found != ''){
						opts.form[i].html_attribs[class_found].value += ' required';
					} else {
						z = opts.form[i].html_attribs.length;
						opts.form[i].html_attribs[ z ] = {'attrib':'class', 'value':'required'};
					}
				}
					
			}
			
			el.data('adc_report:options', opts);
			debug('elem', el);
			debug('setOptions', opts);
		}
		
		function createOptions(el, index){
			opts = el.data('adc_report:options');
			opciones = opts.form[index].options;
			if(typeof opciones === 'function'){
				opciones = opciones();
			}
			
			optnlist = '';
			for(var i in opciones){
				optnlist += '<option value="'+ opciones[i].value +'">'+ opciones[i].text +'</option>';
			}
			debug('createOptions:index'+index, optnlist);
			return optnlist;
		}
		
		function createInputs(el){
			opts = el.data('adc_report:options');
			
			inputs = '';
			objs = opts.form;
			for(var i in objs){
				label='';				
				
				if(objs[i].type != 'hidden'){
					label = '<label for="'+ objs[i].id +'">'+ objs[i].label +'</label>';
				}
				
				input = '';
				has_mask = false;
                _name = objs[i].name?objs[i].name:objs[i].id;
				
				switch(objs[i].type){
					case 'checkbox':
						_val = objs[i].value?objs[i].value:1;
						if(opts.data_send_type!='method'){
							input += '<input type="hidden" id="'+ objs[i].id +'_" name="'+ _name +'" value="0" />';
							input += '<input type="checkbox" id="'+ objs[i].id +'" name="'+ 
								_name +'" value="'+ _val +'" __htmlattribs__ />';
						} else {
							input += '<input type="checkbox" id="'+ objs[i].id +'" name="'+ 
								_name +'" value="'+ objs[i].value +'" __htmlattribs__ />';
						}
						
						break;
					case 'radio':
						input += '<input type="hidden" id="'+ objs[i].id +'_" name="'+ _name +'" value="" />';
						input += '<input type="radio" id="'+ objs[i].id +'" name="'+ 
							_name +'" value="'+ objs[i].value +'" __htmlattribs__ />';
						break;
                                        case 'file':
					case 'text':
					case 'hidden':
						//objs[i].html_attribs
						input += '<input type="'+ objs[i].type +'" id="'+ objs[i].id +'" name="'+ 
							_name +'" value="'+ objs[i].value +'" __htmlattribs__ />';
						if(objs[i].mask){
							has_mask = true;
						}
						break;
					case 'select':
						input += '<select id="'+ objs[i].id +'" name="'+ _name +'" __htmlattribs__ >';
						input += createOptions(el, i);
						input += '</select>';
						break;
					case 'textarea':
						input += '<textarea id="'+ objs[i].id +'" name="'+ _name +
							'" style="width:240px;height:44px;overflow:auto;" value="'+ objs[i].value +'" __htmlattribs__ />';
						break;
					case 'title':
                                                input += '<br/><hr>';
						break;
					case 'date':
						formato = objs[i].date_format
							.replace('yy','2999').replace('y','99')
							.replace('mm','19').replace('m','19')
							.replace('dd','39').replace('d','39');
						
						input += '<input type="text" alt="'+ formato +'" id="'+ objs[i].id +'" name="'+ _name +
							'" value="'+ objs[i].value +'" size="'+objs[i].size+'" date="date:'+ objs[i].date_format +'" __htmlattribs__ />';
						break;
				}
				input = input.replace('__htmlattribs__', createAttribs(el, i));
				
				if(has_mask && 'text,date'.indexOf(objs[i].type)>=0){
					//creando etiqueta alt con la regla de enmascarado
					s_input = input.split(' type');
					s_input[0] = s_input[0] + ' alt="'+ objs[i].mask +'"';
					input = s_input.join(' type');
				}
				
				if(objs[i].div){
					input = '<div class="input">'+label +''+input+'</div>';
				} else {
					input = label +''+ input + '<br />'
				}
				inputs += input;
			}
			
			return inputs;
		}
		
		function createAttribs(el, index){
			opts = el.data('adc_report:options');
			htmlattribs = opts.form[index].html_attribs;
			htmlattribslist = '';
			for (var i in htmlattribs){
				htmlattribslist += htmlattribs[i].attrib + '="' + htmlattribs[i].value + '" ';
			}
			
			return htmlattribslist;
			//debug('createAttribs:'+'index:'+ index, htmlattribslist);
		}
		
		function buildMethodVars(dialog){
			$inputs = dialog.find('input:not(submit):not(reset), select, textarea');
			strVars = '';
			for(var i=0, j=$inputs.length; i<j; i++){
				if($inputs[i].type=='checkbox'){
					if($inputs[i].value & $inputs[i].checked){
						strVars += $inputs[i].value + '/';
					} else if($inputs[i].checked){
						strVars += '1/';
					} else {
						strVars += '0/';
					}
				} else {
					strVars += $inputs[i].value + '/';
				}
			}
			return strVars.substring(0,strVars.length-1);
		}
		
		function debug(text, obj) {
			if(action == 'debug'){
				if(typeof text == 'object'){
					obj = text;
					text = '';
				}
				if (window.console && window.console.log){
					window.console.log(text, obj);
				} else {
					for(var i in obj){
						text += '\n' + i + ': ' + obj[i];
					}
					alert(text);
				}
			}
		}
		
		function showError(msg){
			if(typeof alerta == 'function'){
				alerta(msg, 'adcReport: error');
			} else {
				alert(msg);
			}
		}
		
		function solicitarDatos(elem){
			el = $(elem);
			opc = el.data('adc_report:options');

                        _method = opc.data_send_type != 'post' ? 'get' : 'post';
                        _enctype = opc.enctype != '' ? 'enctype="'+ opc.enctype +'"' : '';
			
			$prompt = $('<div class="d-header"><span class="help">'+ opc.description +'</span><form id="adc_report" name="adc_report" action="'+ opc.url +'" method="'+ _method +'" target="'+ opc.target +'" '+ _enctype +'>'+ createInputs(el) +'</form></div>')
				.dialog({
					title:opc.title,
					width:400,
					height:300,
					hide:'slide',
					modal:opts.modal,
					position:opts.position,
					zIndex:opts.zindex,
					buttons:{
						'Cerrar':function(){
							$(this).dialog('close');
						},
						'Ver':function(){
							//modificando las propiedades del formulario
							$dialog = $(this);
							$form = $dialog.find('form');
							$form.find('div.error-message').remove();
							
							//estableciendo el método de envio de datos para el formulario
							switch (opc.data_send_type){
								case 'post':
									$form.attr('method', 'post')
									break;
								case 'method':
									actn = $form.attr('action').split('?');
									$form.find(':checkbox').removeClass('required');
									actn[0] =  opc.url + '/' + buildMethodVars($form);
									// for(var i=0, j=$inputs.length; i<j; i++){
										// actn[0] += '/' + $inputs[i].value;
									// }
									$form.attr({'method': 'post', 'action': actn.join('?')});
									break;
								case 'get':
								case 'ajax':
								default:
									$form.attr('method', 'get');
							}
							
							//agregando parametros adicionales
							actn = $form.attr('action');
							if(opc.data.length){
								if($form.attr('action').split('?').length>1){
									//actn = $form.attr('action') + '&' + opc.data;
									actn += '&' + opc.data;
								} else {
									//actn = $form.attr('action') + '?' + opc.data;
									actn += '?' + opc.data;
								}
							}
							if(opc.data_send_type !== 'ajax'){
								$form.attr('action', actn)
									.submit(function(e){
										if(opc.close_on_submit){
											$dialog.dialog('close');
										}
									});
							} else {
								$form.unbind('submit').submit(function(e){e.preventDefault();});
								dialogbutton = $('button:contains(Ver):visible','.ui-dialog-buttonpane').attr('disabled','disabled');
								text = dialogbutton.html();
								dialogbutton.html('<span class="ui-icon ui-icon-clock" style="float:left"></span>Espere')
								$.get(actn, $form.serialize(), function(data){
									alerta(data);
									$dialog.find(':text').val('');
									dialogbutton.removeAttr('disabled').html(text);
								});
							}
							
							//validando campos requeridos
							pass = true;
							$inputs = $dialog.find(':input.required').each(function(){
								if (!this.value.trim()){
									$(this).after('<div class="notEmpty error-message" style="display: block;">este valor es necesario</div>');
									pass = false;
								}
							});
							if (pass){
								$form.submit();
							} else {
								showError('hay campos requeridos');
							}
						}
					},
					open:function(event, ui){
						$btnver = $('button:contains(Ver):visible','.ui-dialog-buttonpane');
						$btncerrar = $('button:contains(Cerrar):visible','.ui-dialog-buttonpane');
						// $btnver = $(this).parent().find('button:contains(Ver)');
						// $btncerrar = $(this).parent().find('button:contains(Cerrar)');
						
						$dialog = $(this)
							//focus al primer input
							.find('form input:first').focus().end()
							.find('input[date]').each(function(){
								dformat = $(this).attr('date').split(':')[1];
								$(this).datepicker({
									dateFormat: dformat,
									buttonImage: _WEB_ROOT+'img/calendar.png',
									buttonImageOnly: true,
									duration: '',
									showOn: 'both',
									changeMonth:true,
									changeYear:false					
								});
							}).end()
							//fix para salto de campos con tecla enter
							.find('form :input:visible:enabled:not(:last)').bind('keypress.jumpto', function(e){
								$input = $(this);
								$sibling = $(this).nextAll('input:text:visible:enabled').first();
								
								if(e.which==13 || e.keyCode == 13){
									//test = $('#' + this.id + ' ~ :input:first').focus();
									$sibling.focus();
								}
							}).end()
							//fix para enter en ultimo campo
							.find('form input:last').bind('keypress.enter_fix', function(e){
								if(e.which==13 || e.keyCode == 13){
									$btnver.click();
								}
							}).end()
							//agregando sombreado a ventana
							.parent().css({
								'-moz-box-shadow':'0 0 1em gray',
								'-webkit-box-shadow':'0 0 1em gray',
								'box-shadow':'0 0 1em gray'
							}).end();
						
						//agregando máscaras a los inputs
						$(this).find(':input:text').setMask();
						
						//agregando icono a los botones cerrar y buscar
						if(!$btncerrar.find('span.ui-icon').length){
							$btncerrar.prepend('<span style="float:left;margin-right:10px" class="ui-icon ui-icon-cancel" />');
						}
						
						if(!$btnver.find('span.ui-icon').length){
							$btnver.prepend('<span style="float:left;margin-right:10px" class="ui-icon ui-icon-search" />');
						}
						// $btncerrar.button("option","icons",{primary:'ui-icon-cancel'});
						// $btnver.button("option","icons",{primary:'ui-icon-search'});
						
						if(typeof opc.on_show == 'function'){
							opc.on_show(el, $(this));
						}
						
					},
					close:function(){
						//eliminar la ventana del DOM
						$(this).dialog('destroy').remove();
						//ejecutar el callback, si lo hubiera
						if(typeof opc.callback == 'function'){
							opc.callback(el);
						}
					}
				});	
		}
		
		if(typeof(action) == 'object'){
			options = action;
			action = 'initialize';
		}
		
		//trabajando solo con enlaces
		return this.filter('a[href]').each(function(){
			el = $(this);
			
			switch(action){
				case 'unbind':
					unbind_el(el);
					break;
				case 'initialize':
				case 'debug':
					setOptions(el);
					opts = el.data('adc_report:options');
					el.bind('click', function(e){
						e.preventDefault();
						solicitarDatos(this);
					});
					break;
				default:
			}
			
		}).end();
	};
})(jQuery);